#!/usr/bin/python2.7
from Tkinter import *
import ttk
import RPi.GPIO as GPIO
import time
import binascii
import socket
import struct
import sys
import threading
# To set up the office end Raspberry Pi give it a fixed IP address
# The set the Send IP address of the Field End Raspberry Pi and the
# Receive IP address to that of the Office Raspberry Pi.
# In this case:
# Send 192.168.0.30
# Receive 192.168.0.31

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)


def init(root):
    root.title("RPi TDM")


root = Tk()
#padding window 
content = ttk.Frame(root, padding=(5,5,5,5))
#set window size
root.geometry('230x200')

#text UP or DN - Inputs
global v1, v2, v3, v4, v5, v6, v7, v8
v1 = StringVar()
v2 = StringVar()
v3 = StringVar()
v4 = StringVar()
v5 = StringVar()
v6 = StringVar()
v7 = StringVar()
v8 = StringVar()

#text colour - Inputs
global c1, c2, c3, c4, c5, c6, c7, c8
c1 = StringVar()
c2 = StringVar()
c3 = StringVar()
c4 = StringVar()
c5 = StringVar()
c6 = StringVar()
c7 = StringVar()
c8 = StringVar()

#text UP or DN - Outputs
global v9, v10, v11, v12, v13, v14, v15, v16
v9 = StringVar()
v10 = StringVar()
v11 = StringVar()
v12 = StringVar()
v13 = StringVar()
v14 = StringVar()
v15 = StringVar()
v16 = StringVar()

#text colour - Outputs
global c9, c10, c11, c12, c13, c14, c15, c16
c9 = StringVar()
c10 = StringVar()
c11 = StringVar()
c12 = StringVar()
c13 = StringVar()
c14 = StringVar()
c15 = StringVar()
c16 = StringVar()

global w1
w1 = StringVar()

content.grid(column=0, row=0)

# defining labels for Inputs

ip1_0 = ttk.Label(content, text="Input 1:", justify=LEFT)
ip1_1 = ttk.Label(content, textvariable=v1, foreground=c1.get())
ip2_0 = ttk.Label(content, text="Input 2:", justify=LEFT)
ip2_1 = ttk.Label(content, textvariable=v2, foreground=c2.get())
ip3_0 = ttk.Label(content, text="Input 3:", justify=LEFT)
ip3_1 = ttk.Label(content, textvariable=v3, foreground=c3.get())
ip4_0 = ttk.Label(content, text="Input 4:", justify=LEFT)
ip4_1 = ttk.Label(content, textvariable=v4, foreground=c4.get())
ip5_0 = ttk.Label(content, text="Input 5:", justify=LEFT)
ip5_1 = ttk.Label(content, textvariable=v5, foreground=c5.get())
ip6_0 = ttk.Label(content, text="Input 6:", justify=LEFT)
ip6_1 = ttk.Label(content, textvariable=v6, foreground=c6.get())
ip7_0 = ttk.Label(content, text="Input 7:", justify=LEFT)
ip7_1 = ttk.Label(content, textvariable=v7, foreground=c7.get())
ip8_0 = ttk.Label(content, text="Input 8:", justify=LEFT)
ip8_1 = ttk.Label(content, textvariable=v8, foreground=c8.get())


# placing text 
ip1_0.grid(column=1, row=2)
ip1_1.grid(column=2, row=2)
ip2_0.grid(column=1, row=3)
ip2_1.grid(column=2, row=3)
ip3_0.grid(column=1, row=4)
ip3_1.grid(column=2, row=4)
ip4_0.grid(column=1, row=5)
ip4_1.grid(column=2, row=5)
ip5_0.grid(column=1, row=6)
ip5_1.grid(column=2, row=6)
ip6_0.grid(column=1, row=7)
ip6_1.grid(column=2, row=7)
ip7_0.grid(column=1, row=8)
ip7_1.grid(column=2, row=8)
ip8_0.grid(column=1, row=9)
ip8_1.grid(column=2, row=9)

# defining labels for Outputs

op1_0 = ttk.Label(content, text="Output 1:", justify=LEFT)
op1_1 = ttk.Label(content, textvariable=v9, foreground=c9.get())
op2_0 = ttk.Label(content, text="Output 2:", justify=LEFT)
op2_1 = ttk.Label(content, textvariable=v10, foreground=c10.get())
op3_0 = ttk.Label(content, text="Output 3:", justify=LEFT)
op3_1 = ttk.Label(content, textvariable=v11, foreground=c11.get())
op4_0 = ttk.Label(content, text="Output 4:", justify=LEFT)
op4_1 = ttk.Label(content, textvariable=v12, foreground=c12.get())
op5_0 = ttk.Label(content, text="Output 5:", justify=LEFT)
op5_1 = ttk.Label(content, textvariable=v13, foreground=c13.get())
op6_0 = ttk.Label(content, text="Output 6:", justify=LEFT)
op6_1 = ttk.Label(content, textvariable=v14, foreground=c14.get())
op7_0 = ttk.Label(content, text="Output 7:", justify=LEFT)
op7_1 = ttk.Label(content, textvariable=v15, foreground=c15.get())
op8_0 = ttk.Label(content, text="Output 8:", justify=LEFT)
op8_1 = ttk.Label(content, textvariable=v16, foreground=c16.get())

op1_0.grid(column=3, row=2)
op1_1.grid(column=4, row=2)
op2_0.grid(column=3, row=3)
op2_1.grid(column=4, row=3)
op3_0.grid(column=3, row=4)
op3_1.grid(column=4, row=4)
op4_0.grid(column=3, row=5)
op4_1.grid(column=4, row=5)
op5_0.grid(column=3, row=6)
op5_1.grid(column=4, row=6)
op6_0.grid(column=3, row=7)
op6_1.grid(column=4, row=7)
op7_0.grid(column=3, row=8)
op7_1.grid(column=4, row=8)
op8_0.grid(column=3, row=9)
op8_1.grid(column=4, row=9)


# titles

nameCopy0 = ttk.Label(content, text=" WD ", background=w1.get())
nameCopy0.grid(column=1, row=11)
nameCopy1 = ttk.Label(content, text="walkerworks 2016", foreground="blue")
nameCopy1.grid(column=3, row=11, columnspan=4)
nameCopy2 = ttk.Label(content, text=" ")
nameCopy2.grid(column=1, row=10, columnspan=4)
nameCopy4 = ttk.Label(content, text="TDM Input/Output Status (OFFICE)")
nameCopy4.grid(column=1, row=0, columnspan=4)
nameCopy5 = ttk.Label(content, text=" ")
nameCopy5.grid(column=1, row=1, columnspan=4)


# Resize grip
#ttk.Sizegrip().grid(column=1, row=1, sticky=(S,E))


# inputs 14 & 15 reserved
GPIO.setup(10, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(11, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(12, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(13, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(16, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(17, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(18, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(19, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

# assigning GPIO outputs to make it easier to read
rly1 = 2
rly2 = 3
rly3 = 4
rly4 = 5
rly5 = 6
rly6 = 7
rly7 = 8
rly8 = 9

GPIO.setup(rly1,GPIO.OUT)
GPIO.setup(rly2,GPIO.OUT)
GPIO.setup(rly3,GPIO.OUT)
GPIO.setup(rly4,GPIO.OUT)
GPIO.setup(rly5,GPIO.OUT)
GPIO.setup(rly6,GPIO.OUT)
GPIO.setup(rly7,GPIO.OUT)
GPIO.setup(rly8,GPIO.OUT)

GPIO.output(rly1,GPIO.HIGH)
GPIO.output(rly2,GPIO.HIGH)
GPIO.output(rly3,GPIO.HIGH)
GPIO.output(rly4,GPIO.HIGH)
GPIO.output(rly5,GPIO.HIGH)
GPIO.output(rly6,GPIO.HIGH)
GPIO.output(rly7,GPIO.HIGH)
GPIO.output(rly8,GPIO.HIGH)


# Create a TCP/IP socket
def send ():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_address = ('192.168.0.230', 10000)
    sock.connect(server_address)

    watchdog()
    read_inputs()
    values = (input_1, input_2, input_3, input_4, input_5, input_6, input_7, input_8)
    packer = struct.Struct('8I')
    packed_data = packer.pack(*values)

    try:
    
        # Send data
#        print >>sys.stderr, 'sending "%s"' % binascii.hexlify(packed_data), values
        sock.sendall(packed_data)

    finally:
#        print >>sys.stderr, 'closing socket'
        sock.close()


# Create a TCP/IP socket - Receive
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.0.231', 10000)
sock.bind(server_address)
sock.listen(2)

unpacker = struct.Struct('8I')

# Print comments are left to aid transmission debugging
def receive():
    
#    print >>sys.stderr, 'waiting for a connection'
    connection, client_address = sock.accept()
    try:
        data = connection.recv(unpacker.size)
#        print >>sys.stderr, 'received "%s"' % binascii.hexlify(data)

        global output_1, output_2, output_3, output_4, output_5, output_6, output_7, output_8
        unpacked_data = unpacker.unpack(data)
        (output_1, output_2, output_3, output_4, output_5, output_6, output_7, output_8) = unpacked_data

        
#        print >>sys.stderr, 'unpacked:', unpacked_data
#        print (output_1, output_2, output_3, output_4, output_5, output_6, output_7, output_8)
        read_outputs()

    finally:
        connection.close()


def read_inputs():

    global input_1

    input_1 = GPIO.input(10)
    if input_1:
        v1.set("UP")
        c1.set("green")
        ip1_1.configure(foreground=c1.get())       
    else:
        v1.set("DN")
        c1.set("red")
        ip1_1.configure(foreground=c1.get())
        
    global input_2
    input_2 = GPIO.input(11)
    if input_2:
        v2.set("UP")
        c2.set("green")
        ip2_1.configure(foreground=c2.get())
    else:
        v2.set("DN")
        c2.set("red")
        ip2_1.configure(foreground=c2.get())
        
    global input_3
    input_3 = GPIO.input(12)
    if input_3:
        v3.set("UP")
        c3.set("green")
        ip3_1.configure(foreground=c3.get())
    else:
        v3.set("DN")
        c3.set("red")
        ip3_1.configure(foreground=c3.get())
        
    global input_4
    input_4 = GPIO.input(13)
    if input_4:
        v4.set("UP")
        c4.set("green")
        ip4_1.configure(foreground=c4.get())
    else:
        v4.set("DN")
        c4.set("red")
        ip4_1.configure(foreground=c4.get())
        
    global input_5
    input_5 = GPIO.input(16)
    if input_5:
        v5.set("UP")
        c5.set("green")
        ip5_1.configure(foreground=c5.get())
    else:
        v5.set("DN")
        c5.set("red")
        ip5_1.configure(foreground=c5.get())
        
    global input_6
    input_6 = GPIO.input(17)
    if input_6:
        v6.set("UP")
        c6.set("green")
        ip6_1.configure(foreground=c6.get())
    else:
        v6.set("DN")
        c6.set("red")
        ip6_1.configure(foreground=c6.get())
        
    global input_7
    input_7 = GPIO.input(18)
    if input_7:
        v7.set("UP")
        c7.set("green")
        ip7_1.configure(foreground=c7.get())
    else:
        v7.set("DN")
        c7.set("red")
        ip7_1.configure(foreground=c7.get())
        
    global input_8
    input_8 = GPIO.input(19)                     
    if input_8:
        v8.set("UP")
        c8.set("green")
        ip8_1.configure(foreground=c8.get())
    else:
        v8.set("DN")
        c8.set("red")
        ip8_1.configure(foreground=c8.get())


def read_outputs():      
        if output_1:
            GPIO.output(rly1,GPIO.LOW)
            v9.set("UP")
            c9.set("green")
            op1_1.configure(foreground=c9.get())            
        else:
            GPIO.output(rly1,GPIO.HIGH)
            v9.set("DN")
            c9.set("red")
            op1_1.configure(foreground=c9.get())            

        if output_2:
            GPIO.output(rly2,GPIO.LOW)
            v10.set("UP")
            c10.set("green")
            op2_1.configure(foreground=c10.get())            
        else:
            GPIO.output(rly2,GPIO.HIGH)
            v10.set("DN")
            c10.set("red")
            op2_1.configure(foreground=c10.get())            

        if output_3:
            GPIO.output(rly3,GPIO.LOW)
            v11.set("UP")
            c11.set("green")
            op3_1.configure(foreground=c11.get())            
        else:
            GPIO.output(rly3,GPIO.HIGH)
            v11.set("DN")
            c11.set("red")
            op3_1.configure(foreground=c11.get())            

        if output_4:
            GPIO.output(rly4,GPIO.LOW)
            v12.set("UP")
            c12.set("green")
            op4_1.configure(foreground=c12.get())            
        else:
            GPIO.output(rly4,GPIO.HIGH)
            v12.set("DN")
            c12.set("red")
            op4_1.configure(foreground=c12.get())            

        if output_5:
            GPIO.output(rly5,GPIO.LOW)
            v13.set("UP")
            c13.set("green")
            op5_1.configure(foreground=c13.get())            
        else:
            GPIO.output(rly5,GPIO.HIGH)
            v13.set("DN")
            c13.set("red")
            op5_1.configure(foreground=c13.get())
            
        if output_6:
            GPIO.output(rly6,GPIO.LOW)
            v14.set("UP")
            c14.set("green")
            op6_1.configure(foreground=c14.get())            
        else:
            GPIO.output(rly6,GPIO.HIGH)
            v14.set("DN")
            c14.set("red")
            op6_1.configure(foreground=c14.get())
            
        if output_7:
            GPIO.output(rly7,GPIO.LOW)
            v15.set("UP")
            c15.set("green")
            op7_1.configure(foreground=c15.get())            
        else:
            GPIO.output(rly7,GPIO.HIGH)
            v15.set("DN")
            c15.set("red")
            op7_1.configure(foreground=c15.get())

        if output_8:
            GPIO.output(rly8,GPIO.LOW)
            v16.set("UP")
            c16.set("green")
            op8_1.configure(foreground=c16.get())            
        else:
            GPIO.output(rly8,GPIO.HIGH)
            v16.set("DN")
            c16.set("red")
            op8_1.configure(foreground=c16.get())

        

def grey():
    nameCopy0.configure(background="light grey")


def watchdog():

        w1.set("green")
        nameCopy0.configure(background=w1.get())
        nameCopy0.after(200, grey)



def start_send():
    def tx():
        while True:
            time.sleep(.2)
            send()
            receive()

    t = threading.Thread(target=tx)
    t.daemon=True
    t.start()    


start_send()


init(root)
root.mainloop()